package com.example.supplychainbackend.service.Impl;

import com.example.supplychainbackend.controller.dto.blockchain.UploadInfo;
import com.example.supplychainbackend.controller.dto.quality.*;
import com.example.supplychainbackend.dao.plan.PlanOrderDao;
import com.example.supplychainbackend.dao.production.ProductionSchedulingDao;
import com.example.supplychainbackend.dao.production.ProductionWorkorderDao;
import com.example.supplychainbackend.dao.quality.InspectionBatchDao;
import com.example.supplychainbackend.dao.quality.InspectionOrderDao;
import com.example.supplychainbackend.dao.quality.InspectionRequestDao;
import com.example.supplychainbackend.dao.quality.UnqualifiedDao;
import com.example.supplychainbackend.dao.sales.ContractDao;
import com.example.supplychainbackend.dao.sales.OrderDao;
import com.example.supplychainbackend.entity.production.ProductionSchedulingEntity;
import com.example.supplychainbackend.entity.production.ProductionWorkorderEntity;
import com.example.supplychainbackend.entity.quality.*;
import com.example.supplychainbackend.entity.sales.ContractEntity;
import com.example.supplychainbackend.entity.sales.OrderEntity;
import com.example.supplychainbackend.mapper.QualityMapper;
import com.example.supplychainbackend.service.BlockchainService;
import com.example.supplychainbackend.service.QualityService;
import com.example.supplychainbackend.tool.DateTimeUtils;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.util.List;

@Service
@RequiredArgsConstructor
public class QualityServiceImpl implements QualityService {
    private final QualityMapper mapper;
    private final InspectionBatchDao inspectionBatchDao;
    private final UnqualifiedDao unqualifiedDao;
    private final InspectionRequestDao inspectionRequestDao;
    private final InspectionOrderDao inspectionOrderDao;

    private final ProductionWorkorderDao productionWorkorderDao;
    private final PlanOrderDao planOrderDao;
    private final OrderDao salesOrderDao;
    private final ContractDao contractDao;
    private final ProductionSchedulingDao productionSchedulingDao;

    private final BlockchainService blockchainService;


    @Override
    public List<InspectionBatchDto> listInspectionBatch() {
        return mapper.toInspectionBatchDtoList(inspectionBatchDao.findAll());
    }

    //未使用
    @Override
    public InspectionBatchDto getInspectionBatch(String IBNO) {
        return mapper.toInspectionBatchDto(inspectionBatchDao.findByInspectionBatchNumber(IBNO).get());
    }

    @Override
    @Transactional
    public String createInspectionBatch(InspectionBatchDto form) {
        InspectionBatchEntity entity = mapper.toInspectionBatchEntity(form);
        String  batchNumber = entity.getBatchNumber();
        InspectionRequestEntity irEntity = inspectionRequestDao.findByBatchNumber(batchNumber);
        if (entity.getInspectionType() != 1){
            ProductionSchedulingEntity psEntity = productionSchedulingDao.findByBatchNumber(batchNumber);
            String workOrderNo = psEntity.getWorkOrderNo();ProductionWorkorderEntity pwoEntity = productionWorkorderDao.findByWorkOrderNo(workOrderNo);

            entity.setArea(psEntity.getArea());
            entity.setProductionLine(psEntity.getProductionLine());
            entity.setWorkOrderType(pwoEntity.getWorkOrderType());
            entity.setProcessRoute(psEntity.getProcessRoute());
        }

        entity  = inspectionBatchDao.save(entity);
        Long id = entity.getId();
        //设置检验批单号
        String inspectionBatchNumber = "IB" + DateTimeUtils.getCurrentDateForID() + String.format("%05d",id);
        entity.setInspectionBatchNumber(inspectionBatchNumber);
        inspectionBatchDao.save(entity);
        return inspectionBatchNumber;
    }

    //未使用 或许可以改造成用于同步更新的函数
    @Override
    @Transactional
    public InspectionBatchDto updateInspectionBatch(String IBNO, InspectionBatchDto form) {
        InspectionBatchEntity entity = inspectionBatchDao.findByInspectionBatchNumber(IBNO).get();
        //更新
        mapper.updateInspectionBatchEntity(form,entity);
        return mapper.toInspectionBatchDto(inspectionBatchDao.save(entity));
    }

    //未使用
    @Override
    @Transactional
    public void deleteInspectionBatch(String IBNO) {
        inspectionBatchDao.deleteByInspectionBatchNumber(IBNO);
    }

    @Override
    public List<UnqualifiedDto> listUnqualified() {
        return mapper.toUnqualifiedDtoList(unqualifiedDao.findAll());
    }

    //未使用
    @Override
    public UnqualifiedDto getUnqualified(String id) {
        return mapper.toUnqualifiedDto(unqualifiedDao.findByNonconformingProductNumber(id).get());
    }

    @Override
    @Transactional
    public String createUnqualified(UnqualifiedDto form) {
        UnqualifiedEntity entity = mapper.toUnqualifiedEntity(form);
        InspectionOrderEntity ioEntity = inspectionOrderDao.findByInspectionOrderNumber(form.getInspectionOrderNumber());
        if (ioEntity == null){
            throw new RuntimeException("inspection order not found");
        }
//        String batchNumber = ioEntity.getBatchNumber();
//        ProductionSchedulingEntity psEntity = productionSchedulingDao.findByBatchNumber(batchNumber);
//        if (psEntity == null){
//            throw new RuntimeException("inspection order not found");
//        }
        entity.setInspectionBatchNumber(ioEntity.getInspectionBatchNumber());
        entity.setInspector(ioEntity.getInspector());
        entity.setInspectionTime(ioEntity.getInspectionTime());
        entity.setRequestor(ioEntity.getRequestor());
        entity.setRequestDepartment(ioEntity.getRequestDepartment());
        entity.setRequestTime(ioEntity.getRequestTime());
        entity.setReferenceDocumentType(ioEntity.getReferenceDocumentType());
        entity.setReferenceDocumentNumber(ioEntity.getReferenceDocumentNumber());
        entity.setSourceDocumentType(ioEntity.getSourceDocumentType());
        entity.setSourceDocumentNumber(ioEntity.getSourceDocumentNumber());
        entity.setSourceDocumentLineNumber(ioEntity.getSourceDocumentLineNumber());
        entity.setMaterialName(ioEntity.getMaterialName());
        entity.setMaterialDescription(ioEntity.getMaterialDesc());
        entity.setManufacturer(ioEntity.getManufacturer());
        entity.setManufacturerMaterialCode(ioEntity.getManufacturerMaterialCode());
        entity.setSupplierCode(ioEntity.getSupplierCode());
        entity.setSupplierName(ioEntity.getSupplierName());

        entity.setContractNumber(ioEntity.getContractNumber());
        entity.setContractName(ioEntity.getContractName());
        entity.setSalesOrderNumber(ioEntity.getSalesOrderNumber());
        entity.setSalesOrderName(ioEntity.getSalesOrderName());
//        entity.setWorkOrderNumber(psEntity.getWorkOrderNo());

        List<MeasureEntity> mList = entity.getMeasureLists();
        for (MeasureEntity me:
             mList) {
            me.setId(null);
        }
        entity.setMeasureLists(mList);

        entity = unqualifiedDao.save(entity);
        Long id = entity.getId();
        String nonconformingProductNumber = "NCP" + DateTimeUtils.getCurrentDateForID() + String.format("%05d",id);
        entity.setNonconformingProductNumber(nonconformingProductNumber);
        entity.setOnChain(false);
        unqualifiedDao.save(entity);
        return nonconformingProductNumber;
    }

    @Override
    @Transactional
    public UnqualifiedDto updateUnqualified(String id, UnqualifiedDto form) {
        UnqualifiedEntity entity = unqualifiedDao.findByNonconformingProductNumber(id).get();
        mapper.updateUnqualifiedEntity(form,entity);
        return mapper.toUnqualifiedDto(unqualifiedDao.save(entity));
    }

    @Override
    @Transactional
    public void deleteUnqualified(String id) {
        unqualifiedDao.deleteByNonconformingProductNumber(id);
    }

    @Override
    public List<InspectionRequestListDto> getInspectionRequestList() {
        List<InspectionRequestEntity> entities = inspectionRequestDao.findAll();
        return mapper.toInspectionRequestListDto(entities);
    }
    @Override
    public InspectionRequestDto getByIdInspectionRequest(String id) {
        InspectionRequestEntity entity = inspectionRequestDao.findById(id).get();
        return mapper.toInspectionRequestDto(entity);
    }

    @Override
    public InspectionRequestDto createInspectionRequest(InspectionRequestDto dto) {

        InspectionRequestEntity entity = mapper.toInspectionRequestEntity(dto);
        List<InspectionItemEntity> itemEntities = entity.getInspectionItems();

        //设一些初值
        entity.setStatus(1);
        if (entity.getRequestTime() == null)
            entity.setRequestTime(DateTimeUtils.getCurrentDateTime());
        for (InspectionItemEntity itemEntity:
             itemEntities) {
            itemEntity.setId(null);
        }
        if (entity.getRequestDepartment() == null)
            entity.setRequestDepartment(entity.getInspectionDepartment());
        if (entity.getRequestor() == null)
            entity.setRequestor(entity.getInspector());

        entity.setOnChain(false);
        entity = inspectionRequestDao.save(entity);
        return mapper.toInspectionRequestDto(entity);
    }

    @Override
    public InspectionRequestDto updateInspectionRequest(String id, InspectionRequestDto dto) {
        InspectionRequestEntity entity = inspectionRequestDao.findById(id).get();
        mapper.updateFromDto(entity,dto);
        entity = inspectionRequestDao.save(entity);
        return mapper.toInspectionRequestDto(entity);
    }

    @Override
    public String deleteInspectionRequest(String id) {
        inspectionRequestDao.deleteById(id);
        return id;
    }

    @Override
    public List<InspectionOrderListDto> getInspectionOrderList() {
        List<InspectionOrderEntity> entities = inspectionOrderDao.findAll();
        return mapper.toInspectionOrderListDto(entities);
    }

    @Override
    public InspectionOrderDto getByIdInspectionOrder(String id) {
        InspectionOrderEntity  entity = inspectionOrderDao.findById(id).get();
        return mapper.toInspectionOrderDto(entity);
    }

    @Override
    public InspectionOrderDto createInspectionOrder(InspectionOrderDto dto) {
        InspectionOrderEntity  entity = mapper.toInspectionOrderEntity(dto);
        List<InspectionOrderItemEntity> items = entity.getInspectionItems();
        for (InspectionOrderItemEntity item:
             items) {
            item.setId(null);
        }
        entity.setOnChain(false);
        entity.setStatus(3);
        entity = inspectionOrderDao.save(entity);
        String irID = entity.getInspectionRequestNumber();
        finishInspectionRequest(irID, entity.getInspectionOrderNumber());
        return mapper.toInspectionOrderDto(entity);
    }

    @Override
    public InspectionOrderDto updateInspectionOrder(String id, InspectionOrderDto dto) {
        InspectionOrderEntity  entity = inspectionOrderDao.findById(id).get();
        mapper.updateFromDto(entity,dto);
        entity = inspectionOrderDao.save(entity);
        return mapper.toInspectionOrderDto(entity);
    }

    @Override
    public String deleteInspectionOrder(String id) {
        inspectionOrderDao.deleteById(id);
        return id;
    }
    
    @Override
    @Transactional
    public void beginInspectionRequest(String id) {
        //Request状态修改
        InspectionRequestEntity entity = inspectionRequestDao.findById(id).get();
        entity.setStatus(2);
        inspectionRequestDao.save(entity);
    }

    @Override
    public UploadInfo uploadInspectionRequest(String id) {
        InspectionRequestDto inspectionRequest = this.getByIdInspectionRequest(id);
        if (null!=inspectionRequest){
            UploadInfo txInfo = blockchainService.uploadQualityInspectionReq(id, inspectionRequest.toString());
            inspectionRequest.setOnChain(true);
            inspectionRequest.setCommitTime(txInfo.getCommitTime());
            inspectionRequest.setTransactionId(txInfo.getTransactionId());
            inspectionRequestDao.save(mapper.toInspectionRequestEntity(inspectionRequest));
            return txInfo;
        }
        throw new RuntimeException("inspectionRequest not found");
    }

    @Override
    public UploadInfo uploadInspectionOrder(String id) {
        InspectionOrderDto inspectionOrder = this.getByIdInspectionOrder(id);
        if (null!=inspectionOrder){
            UploadInfo txInfo = blockchainService.uploadQualityInspectionOrder(id, inspectionOrder.toString());
            inspectionOrder.setOnChain(true);
            inspectionOrder.setCommitTime(txInfo.getCommitTime());
            inspectionOrder.setTransactionId(txInfo.getTransactionId());
            inspectionOrderDao.save(mapper.toInspectionOrderEntity(inspectionOrder));
            return txInfo;
        }
        throw new RuntimeException("inspectionOrder not found");
    }

    @Override
    public UploadInfo uploadUnqualified(String id) {
        UnqualifiedDto unqualified = this.getUnqualified(id);
        if (null!=unqualified){
            UploadInfo txInfo = blockchainService.uploadQualityUnqualified(id, unqualified.toString());
            unqualified.setOnChain(true);
            unqualified.setCommitTime(txInfo.getCommitTime());
            unqualified.setTransactionId(txInfo.getTransactionId());
            unqualifiedDao.save(mapper.toUnqualifiedEntity(unqualified));
            return txInfo;
        }
        throw new RuntimeException("unqualified not found");
    }

    public void finishInspectionRequest(String id, String io) {
        //Request状态修改
        InspectionRequestEntity entity = inspectionRequestDao.findById(id).get();
        entity.setStatus(3);
        entity.setInspectionOrderNumber(io);
        inspectionRequestDao.save(entity);
    }

}
